home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / ljbook.arc / LJBOOK.ASM next >
Encoding:
Assembly Source File  |  1987-11-05  |  22.4 KB  |  893 lines

  1.     page    74,132
  2.     title    ljbook - print files 2-up 2-sided on hp ljp
  3.  
  4. ; syntax:    ljbook    filename  [outfile]  [/f] [/p] [/d]
  5.  
  6. ; v0.90 7/02/87 - first flyer
  7. ; v0.97 7/05/87 - add option switches
  8. ; v0.98 7/19/87 - correction for multiples of 4 pages
  9. ; v0.99 8/10/87 - correction for files over 256 pages
  10. ; v1.0 10/05/87 - first public release
  11.  
  12. ;    data area structures
  13.  
  14. psp        struc            ; program segment prefix
  15. psp_int_20    db    0cdh,020h    ; int 20 instruction
  16. psp_top     dw    ?        ; top of memory in paragraph form
  17. psp_resvl    dw    ?        ; reserved
  18. psp_bytes    dw    ?,?        ; bytes available in segment
  19.         db    118 dup (?)    ; unused
  20. psp_parm_len    db    ?        ; characters in parameter list
  21. psp_parms    db    127 dup (?)    ; command parameters
  22. psp        ends
  23.  
  24.  
  25. cseg    segment public para 'code'
  26.     assume cs:cseg, ds:cseg, es:cseg
  27.     org    100h
  28.  
  29. ljbook    proc    far
  30.     lea    sp,word ptr lstack    ; set local stack
  31.     call    chkver            ; check dos version
  32.     call    parms            ; process command line
  33.     call    alloc            ; allocate buffers
  34.     call    open            ; access input file
  35.     call    scan            ; build page table
  36.     call    headers         ; set up (optional) headings
  37.     call    copy            ; print file
  38.     call    close            ; release input file
  39.     mov    byte ptr errlvl,0    ; set good return code
  40.     jmp    short exit        ; and return to system
  41.  
  42. error1:
  43.     mov    dx,offset usage     ; show syntax
  44. error:
  45.     mov    ax,cs            ; insure local regs
  46.     mov    ds,ax            ;
  47.     mov    es,ax            ;
  48.     lea    sp,word ptr lstack    ; insure stck pt
  49.     mov    byte ptr errlvl,1    ; set bad return
  50.     call    prints            ; print error message
  51. exit:
  52.     mov    dx,offset null        ; space last line
  53.     call    prints
  54.     mov    al,byte ptr errlvl    ; get error level
  55.     mov    ah,4ch            ; set exit function
  56.     int    21h            ; return to dos
  57.  
  58.     page
  59. ;
  60. ;    equates, constants, and data areas
  61.  
  62. tab    equ    09h            ; tabby
  63. lf    equ    0ah            ; line-feed
  64. ff    equ    0ch            ; form-feed
  65. cr    equ    0dh            ; carriage return
  66. eof    equ    1ah            ; end-of-file
  67. esc    equ    1bh            ; escape
  68. blank    equ    20h            ; space
  69.  
  70. prn        equ    4        ; handle for standard printer
  71. switch_char    equ    '/'             ; delimiter for command line switches
  72. stopper     equ    255        ; ends text strings
  73.  
  74. version db    cr,lf,'LJBOOK (c) Copyright 1987 by Vernon D. Buerg'
  75.     db    cr,lf,'For personal use only. May not be sold.',stopper
  76. usage    db    cr,lf
  77.     db    cr,lf,'Usage:'
  78.     db    cr,lf,'       ljbook  filename  [outfile] [/f][/p][/d]'
  79.     db    cr,lf
  80.     db    cr,lf,'       /f  put filename in heading of each page'
  81.     db    cr,lf,'       /p  put page number in heading'
  82.     db    cr,lf,"       /d  put today's date/time in heading"
  83. null    db    cr,lf,stopper,26
  84.  
  85. flags    db    0            ; procesing options
  86.  swf    equ    1            ; /f = filename in heading
  87.  swd    equ    2            ; /d = put today's date/time in heading
  88.  swp    equ    4            ; /p = put page numbers in heading
  89.  swm    equ    8            ; /m = left margin (not implemented)
  90.  swt    equ    16            ; /t = title supplied (not implemented)
  91.  
  92. errlvl    db    0            ; dos error level returned
  93. lastchr db    0            ; previously read char
  94.  
  95. max    dw    0            ; maximum pages/table entries
  96. min    dw    128            ; minimum
  97.  
  98. atable    dw    offset table        ; offset to next table entry
  99. btable    dw    offset table        ; offset for right side
  100.  
  101. pages    dw    1            ; number of pages
  102. sides    dw    0            ; number of two-up pages
  103. sheets    dw    0            ; number of sheets
  104.  
  105. lpp    equ    66            ; lines per page
  106. lcnt    dw    0            ; current lines on page
  107. cpl    equ    80            ; characters per line
  108. linelen dw    0            ; length of current line
  109.  
  110. filepos dw    0,0            ; current file offset
  111.  
  112. ibuf    dw    offset table        ; next input character
  113. ilen    dw    0            ; bytes in buffer
  114. ihandle dw    0            ; input handle
  115. msgopni db    cr,lf,"Can't open input file - "
  116. ifile    db    76 dup (0),255        ; input file name
  117.  
  118. ohandle dw    prn            ; output handle
  119. msgopno db    cr,lf,"Can't open output file - "
  120. ofile    db    76 dup (0),255        ; output file name
  121.  
  122.     page
  123. ;
  124. ;    print command codes
  125.  
  126. init    equ    $            ; initilization strings
  127.     db    27,'&l1O'               ; landscape
  128.     db    27,'(s0p'               ; fixed spacing                 ;099
  129.     db         '16.66h'           ; font pitch                    ;099
  130.     db         '8.5v'             ; point size                    ;099
  131.     db         '0d'               ; style                         ;099
  132.     db         '0b'               ; weight                        ;099
  133.     db         '0T'               ; typeface                      ;099
  134.     db    27,'&l8d'               ; 8 lpi                         ;099
  135.     db         '1e'               ; top margin                    ;099
  136.     db         '67f'              ; text length, 8x8.5=68 lines   ;099
  137.     db         '5.5C'             ; vertical motion index = n/48  ;099
  138.     db    esc,'&s0C'              ; enable line wrap
  139. initlen equ    $-init
  140.  
  141.                     ; printer codes for left side
  142. left_side    db    27,'9',cr       ;  clear margins
  143.         db    27,'&a1r'       ;  line 1                       ;099
  144.         db        'a0l'       ;  left margin                  ;099
  145.         db        'a79M'      ;  right margin                 ;099
  146.         db    cr        ;  column 0
  147. left_side_len    equ    $-left_side
  148.  
  149.                     ; printer codes for right side
  150. right_side    db    27,'9',cr       ;  clear margins
  151.         db    27,'&a1r'       ;  line 1                       ;099
  152.         db         '96l'      ;  left margin                  ;099
  153.         db         '175M'     ;  right margin                 ;099
  154.         db    cr        ;  column 94 (col 1)
  155. right_side_len    equ    $-right_side
  156.  
  157. endpage db    ff            ; printer codes to write at end of page
  158. endlen    equ    $-endpage
  159.  
  160.     page
  161. ;
  162. ;    messages
  163.  
  164. info    db    cr,lf,lf
  165. infonr    db    '       sheets to print.',stopper
  166.  
  167. side1    db    cr,lf,cr,lf,'Printing side 1 ...',stopper
  168. side2    db    cr,lf,cr,lf,'Printing side 2 ...',stopper
  169.  
  170. prompt    db    cr,   'Side 1 printed.    ',cr,lf
  171.     db    cr,lf,'Place printed paper back in paper tray, '
  172.     db    cr,lf,'and press ENTER when ready ...',stopper
  173.  
  174. ended    db    cr,   'Side 2 printed.    ',cr,lf,stopper
  175.  
  176. msgmem    db    cr,lf,'Insufficient memory',255
  177. msgver    db    cr,lf,'Incorrect DOS version',255
  178. msgread db    cr,lf,'Error reading file',255
  179.  
  180.     page
  181. ;
  182. ;    page headings and titles
  183.  
  184. page_const    db    'Page '
  185.  
  186. lheader     db    cr        ; line 1 of left page
  187. left_page    equ    $        ; spot for 'Page'
  188. left_pagenr    equ    $+4        ; spot for page number
  189. left_date    equ    lheader+18    ; spot for date
  190. left_time    equ    lheader+35    ; spot for time
  191.         db    80 dup (' ')    ; supplied title
  192. left_fname    equ    $-1        ; last char of leftmost filename
  193.         db    cr,lf,lf    ; blank line 2
  194. lheader_len    equ    $-lheader    ; length of titles
  195.  
  196. rheader     db    cr        ; line 1 of right page
  197. right_fname    equ    $        ; first char of rightmost filename
  198.         db    80 dup (' ')    ; supplied title
  199. right_page    equ    $-4-6        ; spot for 'Page'
  200. right_pagenr    equ    $-6        ; spot for page number
  201. right_time    equ    right_page-12    ; spot for time
  202. right_date    equ    right_time-17
  203.         db    cr,lf,lf    ; blank line 2
  204. rheader_len    equ    $-rheader
  205.  
  206. months    db    ' Jan'
  207.     db    ' Feb'
  208.     db    ' Mar'
  209.     db    ' Apr'
  210.     db    ' May'
  211.     db    'June'
  212.     db    'July'
  213.     db    ' Aug'
  214.     db    ' Sep'
  215.     db    ' Oct'
  216.     db    ' Nov'
  217.     db    ' Dec'
  218.  
  219.     page
  220. ;
  221. ;    check dos version
  222.  
  223. chkver    proc    near            ;
  224.     mov    dx,offset version    ; display verion number
  225.     call    prints            ;
  226.     mov    ah,30h            ; get dos version
  227.     int    21h            ;
  228.     cmp    al,2            ; at least 2.0?
  229.     jae    chkdver         ; yes, good
  230.     mov    dx,offset msgver    ; no, complain
  231.     jmp    error            ; and exit
  232. chkdver:                ;
  233.     ret                ;
  234. chkver    endp                ;
  235.  
  236.     page
  237. ;
  238. ;    parse command line
  239.  
  240. parms    proc    near
  241.     mov    si,offset psp_parm_len    ; point to command line
  242.     sub    cx,cx            ; to receive command line length
  243.     lodsb
  244.     or    cl,al            ; any command line?
  245.     jnz    switches        ; yes, continue
  246.     jmp    error1            ; no, show usage
  247.  
  248. switches:
  249.     mov    di,offset psp_parms    ; offset to command parameters
  250. switches0:
  251.     mov    al,switch_char        ; see if ANY switches
  252.     repne    scasb
  253.     jne    switched        ; none, skip next
  254.     jcxz    switched        ; no more data
  255.     mov    byte ptr -1[di],cr    ; terminate command line at first /
  256.     cmp    byte ptr -2[di],blank    ;
  257.     jne    switchesa        ;
  258.     mov    byte ptr -2[di],cr    ;
  259. switchesa:
  260.     mov    si,di            ; point to next char
  261.     lodsb                ; get char following switch char
  262.     cmp    al,'a'                  ;  and make it upper case
  263.     jb    switches1        ;
  264.     sub    al,blank        ;
  265. switches1:
  266.     cmp    al,'F'                  ; show file name?
  267.     jne    switches2        ;
  268.     or    flags, swf        ;
  269. switches2:
  270.     cmp    al,'D'                  ; show date/time?
  271.     jne    switches3        ;
  272.     or    flags, swd        ;
  273. switches3:
  274.     cmp    al,'P'                  ; create page numbers?
  275.     jne    switches4        ;
  276.     or    flags, swp        ;
  277. switches4:
  278.     cmp    al,'M'                  ; add left margin?
  279.     jne    switches5        ;
  280.     or    flags, swm        ;
  281. switches5:
  282.     cmp    al,'T'                  ; add user title?
  283.     jne    switches6        ;
  284.     or    flags, swt        ;
  285. switches6:
  286.     jcxz    switched        ; any more operands?
  287.     jmp    switches0        ; yup
  288.  
  289.     page
  290. ;
  291. ;    get file names for input and output (printer) files
  292.  
  293. switched:
  294.     mov    si,offset psp_parms    ; point to command line again
  295.     sub    ch,ch            ;
  296.     mov    cl,byte ptr ds:[psp_parm_len] ; get length back
  297. parm1:
  298.     lodsb                ; next char
  299.     cmp    al,blank        ; skip leading blanks
  300.     je    parm1a            ;
  301.     cmp    al,tab            ; skip tabs, too
  302.     jne    parm2            ;
  303. parm1a: loop    parm1            ;
  304.     jmp    error1            ; operand(s) missing
  305.  
  306. parm2:
  307.     mov    di,offset ifile     ; target for input file name
  308.     sub    cx,1            ; account for last lodsb
  309.     jge    parm3            ; if more to process
  310.     jmp    error1            ; operand(s) missing
  311. parm3:
  312.     stosb                ; previous char
  313.     lodsb                ; next char
  314.     cmp    al,blank        ; have operand separator?
  315.     jbe    parm4            ; yes, have first op
  316.     loop    parm3            ;
  317.     stosb                ;
  318.     jmp    short parm8        ; no second operand, use printer
  319.  
  320. parm4:
  321.     mov    di,offset ofile     ; target for output file name
  322.     jcxz    parm8            ; if no second operand
  323. parm5:
  324.     lodsb                ; skip intervening delimiters
  325.     cmp    al,blank        ;
  326.     je    parm6            ;
  327.     cmp    al,cr            ; end of parameters?
  328.     je    parm8            ; yes, just one operand
  329.     cmp    al,tab            ; skip tabs
  330.     jne    parm7            ;
  331. parm6:    loop    parm5            ; until no more command parameters
  332.     jmp    short parm8        ; none left
  333.  
  334. parm7:                    ; copy 2nd parm to output file name
  335.     stosb                ; its first/next char
  336.     lodsb                ; get next command line char
  337.     cmp    al,cr            ; end of it?
  338.     jbe    parm8            ; yes, have both operands now
  339.     loop    parm7            ;
  340. parm8:    ret                ;
  341. parms    endp
  342.  
  343.     page
  344. ;
  345. ;    allocate memory and buffer(s)
  346.  
  347. alloc    proc   near
  348.     mov    ax,word ptr ds:psp_bytes ;size of segment
  349.     sub    ax,pgmsize        ; less program size
  350.     sub    dx,dx            ;
  351.     mov    cx,ltable        ; size of each table entry
  352.     div    cx            ;  to get maximum entries
  353.     mov    max,ax            ;
  354.     cmp    ax,min            ; have enough?
  355.     jb    alloc_err        ; no,
  356.     mov    cx,ax            ; clear table
  357.     mov    di,offset table     ;
  358.     sub    ax,ax            ; to zeros
  359. alloc1:
  360.     stosw
  361.     stosw
  362.     stosw
  363.     loop    alloc1
  364.     ret
  365.  
  366. alloc_err:
  367.     mov    dx,offset msgmem    ; insufficient memory
  368.     jmp    error            ; return and exit
  369. alloc    endp
  370.  
  371. open    proc    near
  372.     mov    dx,offset ifile     ; input file name
  373.     mov    ax,3d00h        ; for input
  374.     int    21h            ;
  375.     jc    open_err1        ;
  376.     mov    word ptr ihandle,ax    ; save input file handle
  377.  
  378.     cmp    byte ptr ofile,0    ; was output file specified?
  379.     je    open_exit        ; no, use default printer
  380.     mov    dx,offset ofile     ; output file name
  381.     mov    ah,3ch            ;  for create
  382.     sub    cx,cx            ; normal attribute
  383.     int    21h            ;
  384.     jc    open_err2        ; failed
  385.     mov    ohandle,ax        ; save new output handle
  386. open_exit:
  387.     ret                ;
  388.  
  389. open_err1:
  390.     mov    dx,offset msgopni    ; input failed to open
  391.     jmp    error            ; return and exit
  392.  
  393. open_err2:
  394.     mov    dx,offset msgopno    ; output failed to open
  395.     jmp    error            ; return and exit
  396. open    endp
  397.     page
  398. ;
  399. ;    close all files
  400.  
  401. close    proc    near            ; close input and output files
  402.     mov    bx,word ptr ihandle    ; get input handle
  403.     or    bx,bx            ; was it opened?
  404.     jz    close2            ; no, skip it
  405.     mov    ah,3eh            ; yes, close it
  406.     int    21h            ;
  407.     mov    word ptr ihandle,0    ; mark it closed
  408. close2:
  409.     mov    bx,word ptr ohandle    ; get output handle
  410.     cmp    bx,prn            ; is it standard printer?
  411.     jbe    closed            ; yes, skip it
  412.     mov    ah,3eh            ; yes, close it
  413.     int    21h            ;
  414.     mov    word ptr ohandle,0    ; mark it closed
  415. closed:
  416.     ret
  417. close    endp
  418.  
  419.     page
  420. ;
  421. ;    Print string like int 21h function 9
  422.  
  423. prints    proc    near            ; dx has offset to string
  424.     push    di            ;  ending in char x'ff'
  425.     push    bx            ;
  426.     push    cx            ;
  427.     mov    di,dx            ; ptr to string text
  428.     mov    cx,-1            ; overall text length
  429.     mov    al,255            ; find ending hex ff
  430.     repne    scasb            ;
  431.     not    cx            ; length is bytes scanned
  432.     mov    bx,1            ; standard output device
  433.     mov    ah,40h            ; write to a file or handle
  434.     int    21h            ;
  435.     pop    cx            ; recover registers
  436.     pop    bx            ;
  437.     pop    di            ;
  438.     ret                ;
  439. prints    endp
  440.  
  441.     page
  442. ;
  443. ;    scan input file for page markers
  444.  
  445. scan    proc    near
  446.     mov    bx,atable        ; pointer to table entry
  447.     mov    al,0            ; no history
  448. scanread:
  449.     mov    byte ptr lastchr,al    ; save previous character
  450.     call    getc            ; get next char
  451.     jc    scanned         ; all done
  452.     inc    word ptr [bx]        ; bump page size
  453.     cmp    al,esc            ; is it control char?
  454.     jbe    scan0            ; yes, don't bump line length
  455.     inc    word ptr linelen    ; bump line length
  456. scan0:
  457.     cmp    word ptr linelen,cpl    ; reached line limit?
  458.     ja    scan1            ; yes, force new line
  459.     cmp    al,lf            ; new line?
  460.     jne    scan2            ; no,
  461. scan1:
  462.     inc    lcnt            ; yes, bump line count
  463.     mov    word ptr linelen,0    ; reset line length
  464.     cmp    lcnt,lpp        ; reached end of page?
  465.     jb    scanread        ; no, continue
  466.     jmp    short scan3        ; yes, simulate end of page
  467. scan2:
  468.     cmp    al,ff            ; found start of next page?
  469.     jne    scanread        ; no, keep reading
  470. scan3:
  471.     cmp    lcnt,0            ; any lines yet?
  472.     jne    scan4            ; yes, have lines to print
  473.     cmp    lastchr,lf        ; no, but was previous an lf?
  474.     je    scanread        ; yes, already have page boundary
  475. scan4:
  476.     inc    pages            ; bump page count
  477.     mov    lcnt,0            ; reset line counter
  478.     add    bx,ltable        ; point to next table entry
  479.     mov    atable,bx        ;
  480.     mov    di,filepos        ; get
  481.     mov    dx,filepos+2        ;  file
  482.     mov    word ptr 2[bx],di    ;   position
  483.     mov    word ptr 4[bx],dx    ;    for next page
  484.     jmp    short scanread        ; look for next page
  485.  
  486. scanned:
  487.     ret                ; done, return
  488. scan    endp
  489.  
  490.     page
  491. ;
  492. ;    get next byte from read buffer
  493.  
  494.  
  495. getc    proc    near
  496.     sub    ilen,1            ; decr byte count
  497.     jl    getb            ; no more, get next block
  498.     mov    si,word ptr ibuf    ; next input char
  499.     lodsb                ; get next char
  500.     mov    word ptr ibuf,si    ;
  501.     mov    byte ptr lastchr,al    ; save previous character
  502.     cmp    al,eof            ; logical end of file?
  503.     je    getcx            ; yes, set return
  504.     add    filepos,1        ; bump file position
  505.     adc    filepos+2,0        ;
  506.     clc                ; set good return
  507.     ret                ;
  508.  
  509. getb:                    ; read next block
  510.     push    bx            ; save index reg
  511.     mov    bx,word ptr ihandle    ; input handle
  512.     mov    cx,bufsize        ; size to read
  513.     mov    dx,offset buffer    ; data area
  514.     mov    word ptr ibuf,dx    ; reset next char ptr
  515.     mov    ah,3fh            ; read from file
  516.     int    21h            ;
  517.     pop    bx            ; recover index reg
  518.     jc    getcx            ; none, exit
  519.     or    ax,ax            ; end of file?
  520.     jz    getcx            ; yes, return cf
  521.     mov    word ptr ilen,ax    ; save count read
  522.     jmp    short getc        ; and get next char
  523.  
  524. getcx:                    ; return with eof indication
  525.     stc                ;  of cf=1
  526.     ret
  527. getc    endp
  528.  
  529.     page
  530. ;
  531. ;    copy file to printer (or output file)
  532.  
  533. copy    proc    near
  534.     add    pages,3         ; round up pages        ;099
  535.     and    pages,0fffch        ;  to multiple of four        ;098
  536.     mov    ax,pages        ;
  537.     shr    ax,1            ; number of two-up pages
  538.     mov    sides,ax        ;
  539.     shr    ax,1            ; number of pages, two sides each
  540.     mov    sheets,ax        ;
  541.     mov    si,offset infonr    ; tell how many sheets
  542.     call    format            ;
  543.     mov    dx,offset info        ;
  544.     call    prints            ;
  545.  
  546.     push    sheets            ; save for second pass
  547.  
  548.     mov    ax,pages        ; number of pages
  549.     dec    ax            ; adjust for zero indexing
  550.     mov    cx,ltable        ; get table
  551.     mul    cx            ;   pointer
  552.     add    ax,offset table     ;    for last entry
  553.     mov    btable,ax        ; and save it
  554.  
  555.     mov    ax,offset table     ; ptr for first left side entry
  556.     mov    atable,ax        ;  and save it
  557.  
  558.     mov    dx,offset init        ; initialization codes
  559.     mov    cx,initlen        ; length of start-of-page codes
  560.     mov    bx,ohandle        ; write to output file
  561.     mov    ah,40h            ; write to file
  562.     int    21h            ;
  563.  
  564.     mov    dx,offset side1     ;
  565.     call    prints            ;
  566.     call    printer         ; print first side
  567.  
  568.     pop    sheets            ; get page count back
  569.     mov    dx,offset prompt    ; ask to turn paper over
  570.     call    prints            ;
  571.     mov    ax,0c08h        ; clear console
  572.     mov    dl,0ffh         ; direct console i/o
  573.     int    21h            ;
  574.  
  575.     mov    dx,offset side2     ;
  576.     call    prints            ;
  577.     call    printer         ; print second side
  578.     mov    dx,offset ended     ; tell them we're done
  579.     call    prints            ;
  580.     ret
  581.  
  582. printer proc    near            ; print one side of page
  583. doleft:
  584.     mov    dx,offset left_side    ; codes at begin of page
  585.     mov    cx,left_side_len    ; length of start-of-page codes
  586.     mov    bx,ohandle        ; write to output file
  587.     mov    ah,40h            ; write to file
  588.     int    21h            ; via dos
  589.  
  590.     test    flags,swp        ; want page number?
  591.     jz    doleft1         ; no
  592.     mov    si,offset left_pagenr    ; yes, format it
  593.     mov    ax,btable        ; offset to page table entry
  594.     sub    ax,offset table     ; offset into table
  595.     sub    dx,dx            ; clear for divide
  596.     add    ax,ltable        ; start with page 1
  597.     mov    cx,ltable        ; get page number
  598.     div    cx            ;
  599.     call    format            ;
  600. doleft1:
  601.     mov    dx,offset lheader    ; supplied titles
  602.     mov    cx,lheader_len        ; their length
  603.     mov    ah,40h            ; write to file
  604.     int    21h            ; via dos
  605.  
  606.     mov    si,btable        ; left side table entry
  607.     mov    cx,word ptr 4[si]    ; get file offset
  608.     mov    dx,word ptr 2[si]    ;
  609.     mov    ax,4200h        ; position from front
  610.     mov    bx,ihandle        ;  of input file
  611.     int    21h            ;
  612.  
  613.     mov    si,btable        ; table entry
  614.     mov    cx,word ptr 0[si]    ; length of page
  615.     sub    cx,1            ; omit ending formfeed
  616.     jle    doright         ; empty
  617.     mov    dx,offset buffer    ; read data area
  618.     mov    ah,3fh            ; read from file
  619.     int    21h            ;
  620.  
  621.     mov    bx,ohandle        ; write to output file
  622.     mov    ah,40h            ; write to file
  623.     int    21h            ;
  624.  
  625. doright:
  626.     sub    btable,ltable+ltable    ; next table entry
  627.  
  628.     mov    dx,offset right_side    ; codes at begin of right side
  629.     mov    cx,right_side_len    ; length of start-of-page codes
  630.     mov    bx,ohandle        ; write to output file
  631.     mov    ah,40h            ; write to file
  632.     int    21h            ; via dos
  633.  
  634.     test    flags,swp        ; want page number?
  635.     jz    doright1        ; no
  636.     mov    si,offset right_pagenr    ; yes, format it
  637.     mov    ax,atable        ; offset to page table entry
  638.     sub    ax,offset table     ; offset into table
  639.     sub    dx,dx            ; clear for divide
  640.     add    ax,ltable        ; start with page 1
  641.     mov    cx,ltable        ; get page number
  642.     div    cx            ;
  643.     call    format            ;
  644. doright1:
  645.     mov    dx,offset rheader    ; supplied titles
  646.     mov    cx,rheader_len        ; their length
  647.     mov    ah,40h            ; write to file
  648.     int    21h            ; via dos
  649.  
  650.     mov    si,atable        ; right side table entry
  651.     mov    cx,word ptr 4[si]    ; get file offset
  652.     mov    dx,word ptr 2[si]    ;
  653.     mov    ax,4200h        ; position from front
  654.     mov    bx,ihandle        ;  of input file
  655.     int    21h            ;
  656.  
  657.     mov    si,atable        ; table entry
  658.     mov    cx,word ptr 0[si]    ; length of page
  659.     sub    cx,1            ; omit formfeed
  660.     jle    doright2        ; empty
  661.     mov    dx,offset buffer    ; read data area
  662.     mov    ah,3fh            ; read from file
  663.     int    21h            ;
  664.  
  665.     mov    bx,ohandle        ; write to output file
  666.     mov    ah,40h            ; write to file
  667.     int    21h            ;
  668.  
  669. doright2:
  670.     mov    dx,offset endpage    ; eject at end of page
  671.     mov    cx,endlen        ; length of end-of-page codes
  672.     mov    bx,ohandle        ; write to output file
  673.     mov    ah,40h            ; write to file
  674.     int    21h            ;
  675.  
  676.     add    atable,ltable+ltable    ; next table entry
  677.  
  678.     sub    sheets,1        ; decr page count
  679.     jz    printer_exit        ; no more pages
  680.     jmp    doleft            ; do next page
  681.  
  682. printer_exit:                ;
  683.     ret                ; done, exit
  684. printer endp
  685. copy    endp
  686.  
  687.  
  688. ljbook    endp
  689.  
  690.     page
  691. ;
  692. ;    convert a binary number to ascii
  693.  
  694.     public    format
  695. format    proc    near            ;format a block number
  696.     sub    dx,dx
  697. formatd:push    ax
  698.     push    bx            ;value in dx:ax
  699.     push    cx            ;offset to target
  700.     push    dx
  701.     push    di
  702.  
  703.     mov    bx,si            ;save target offset
  704.     mov    cx,6            ;clear target
  705. form0:    mov    byte ptr [si],' '
  706.     inc    si
  707.     loop    form0
  708.  
  709.     mov    cx,4            ;four times
  710.     sub    di,di            ;divisor offset
  711.     mov    si,bx            ;restore target ptr
  712. form1:    or    ax,ax            ;it is zero?
  713.     jnz    form10
  714.     or    dx,dx
  715.     jz    form2
  716. form10: div    tenk[di]
  717.     aam                ;make al into bcd
  718. form2:    or    ax,'00'                 ; and to ascii
  719.     xchg    al,ah
  720.     or    byte ptr [si],al
  721.     mov    byte ptr [si]+1,ah
  722.     inc    si            ;next digit
  723.     add    di,2            ;next divisor
  724.     mov    ax,dx            ;copy remainder
  725.     sub    dx,dx            ; and clear hi-word
  726.     loop    form1
  727.  
  728.     aam                ;make al into bcd
  729.     or    ax,'00'                 ; and to ascii
  730.     xchg    al,ah
  731.     mov    byte ptr [si]+1,ah
  732.     mov    cx,5            ;suppress leading zeros
  733.     mov    si,bx            ;get target offset back
  734. form3:    cmp    byte ptr [si],'0'
  735.     jne    form4
  736.     mov    byte ptr [si],' '
  737.     inc    si
  738.     loop    form3
  739.  
  740. form4:    pop    di
  741.     pop    dx
  742.     pop    cx
  743.     pop    bx
  744.     pop    ax
  745.     ret
  746.  
  747. tenk    dw    10000,1000,100,10    ;for converting numbers
  748. format    endp
  749.  
  750.     page
  751. ;
  752. ;    set up optional page headings
  753.  
  754. headers proc    near
  755.     test    flags,swf+swd+swp+swt    ; any header options?
  756.     jz    header_exit        ; no, that was easy
  757.     test    flags,swf        ; want file name?
  758.     jz    header2         ; no
  759.     mov    cx,40            ;
  760.     mov    si,offset ifile     ; yes, copy filename
  761.     mov    di,offset right_fname    ;
  762. headera:
  763.     lodsb                ; copy up to end of name
  764.     cmp    al,0            ;
  765.     je    headerb         ;
  766.     stosb                ;
  767.     loop    headera         ;
  768. headerb:
  769.     mov    cx,40            ;
  770.     std                ; backwards
  771.     mov    si,offset ifile+39    ;  from end of filename
  772.     mov    di,offset left_fname    ;   to end of left filename area
  773. header1:
  774.     lodsb                ;
  775.     cmp    al,0            ; found end of name?
  776.     loope    header1         ; not yet
  777.     inc    cx            ;
  778.     inc    si            ;
  779.     rep    movsb            ; yes, copy it
  780. header2:
  781.     cld                ; restore direction
  782.     test    flags,swp        ; want page numbering?
  783.     jz    header4         ; no,
  784.     mov    si,offset page_const    ; yes, copy constant
  785.     mov    di,offset left_page    ;  'page' to left side
  786.     mov    cx,5            ;
  787.     rep    movsb            ;
  788.     mov    si,offset page_const    ;
  789.     mov    di,offset right_page    ;
  790.     mov    cx,5            ;
  791.     rep    movsb            ;
  792. header4:
  793.     test    flags,swd        ; want date in title?
  794.     jz    header5         ; no, skip next
  795.     mov    di,offset left_date    ; format today's date
  796.     call    getdate         ;  in left side titles
  797.     mov    di,offset left_time    ; format today's time
  798.     call    gettime         ;  in left side titles
  799.     mov    di,offset right_date    ; format today's date
  800.     call    getdate         ;  in right side titles
  801.     mov    di,offset right_time    ; format today's time
  802.     call    gettime         ;  in right side titles
  803. header5:
  804. header_exit:
  805.     ret
  806. headers endp
  807.  
  808.     page
  809. ;
  810. ;    get and format current date
  811. ;
  812. ;    input: DI points to target area
  813.  
  814. getdate proc    near
  815.     mov    ah,2ah            ; get date
  816.     int    21h            ;
  817.     push    cx            ; save year
  818.     push    dx            ; save day
  819.  
  820.     mov    bl,dh            ; get month
  821.     sub    bh,bh            ; form index
  822.     shl    bx,1            ;  into month
  823.     shl    bx,1            ;   name list
  824.     lea    si,offset months-4[bx]    ; copy month name
  825.     mov    cx,4            ;
  826.     rep    movsb            ;
  827.     mov    al,' '                  ; add space
  828.     stosb                ;
  829.  
  830.     pop    dx            ; recover day
  831.     mov    al,dl            ; get day
  832.     aam                ;
  833.     xchg    al,ah            ;
  834.     or    ax,'00'                 ;
  835.     stosw                ;
  836.     mov    ax,' ,'                 ; add delimiter
  837.     stosw                ;
  838.     mov    ax,'91'                 ; add century
  839.     stosw
  840.  
  841.     pop    ax            ; get year(19xx)
  842.     sub    ax,1900         ;
  843.     aam                ;
  844.     xchg    al,ah            ;
  845.     or    ax,'00'                 ;
  846.     stosw                ;
  847.     ret                ; return
  848. getdate endp
  849.  
  850.     page
  851. ;
  852. ;    get current time
  853. ;
  854. ;    input: DI points to target area
  855.  
  856. gettime proc    near
  857.     mov    ah,2ch            ; dos time function
  858.     int    21h            ;
  859.     mov    al,ch            ; get hours
  860.     aam                ;
  861.     xchg    al,ah            ;
  862.     or    ax,'00'                 ;
  863.     stosw                ;
  864.     mov    al,':'                  ; add delimiter
  865.     stosb                ;
  866.     mov    al,cl            ; get minutes
  867.     aam                ;
  868.     xchg    al,ah            ;
  869.     or    ax,'00'                 ;
  870.     stosw                ;
  871.     ret                ; return
  872. gettime endp
  873.  
  874.     page
  875. ;
  876. ;    tables and dynamic data areas
  877.  
  878.     even
  879. bufsize equ    18*1024         ; input file buffer size
  880. buffer    db    0
  881.  
  882. lstack    equ    buffer + bufsize + 512    ; local stack
  883.  
  884. ltable    equ    6            ; size of each entry
  885. table    equ    lstack+2        ; page/offset table
  886.                     ;  0,2     page size in bytes
  887.                     ;  2,4     file offset to top of page
  888.  
  889. pgmsize equ    lstack-cseg+512     ; paragraphs in module
  890.  
  891. cseg    ends
  892.     end    ljbook
  893.